package ar.com.fiuba.ElectronicCircuitAnalyst.application.impl;

import org.apache.log4j.Logger;

import ar.com.fiuba.ElectronicCircuitAnalyst.application.api.CircuitDto;
import ar.com.fiuba.ElectronicCircuitAnalyst.application.api.CircuitService;
import ar.com.fiuba.ElectronicCircuitAnalyst.domain.api.Circuit;
import ar.com.fiuba.ElectronicCircuitAnalyst.domain.api.CircuitFactory;
import ar.com.fiuba.ElectronicCircuitAnalyst.domain.api.repository.CircuitRepository;
import ar.com.fiuba.ElectronicCircuitAnalyst.domain.api.repository.DuplicateElementException;
import ar.com.fiuba.ElectronicCircuitAnalyst.domain.api.repository.ElementNotFoundException;
import ar.com.fiuba.ElectronicCircuitAnalyst.domain.exceptions.AlreadyExistingCircuitElementException;
import ar.com.fiuba.ElectronicCircuitAnalyst.domain.exceptions.CircuitElementNotFoundException;
import ar.com.fiuba.ElectronicCircuitAnalyst.domain.exceptions.InvalidCircuitElementException;

public class CircuitServiceImpl implements CircuitService {

	private Logger log = Logger.getLogger(CircuitServiceImpl.class);

	private CircuitFactory circuitFactory;

	private CircuitRepository circuitRepository;

	public CircuitServiceImpl(CircuitFactory circuitFactory, CircuitRepository circuitRepository) {
		this.circuitFactory = circuitFactory;
		this.circuitRepository = circuitRepository;
	}

	public Circuit makeCircuit(CircuitDto data) throws InvalidCircuitElementException,
			AlreadyExistingCircuitElementException {
		log.info("Making \"" + data.getName() + "\" circuit.");
		Circuit theCircuit = circuitFactory.makeCircuit(data);
		try {
			circuitRepository.save(theCircuit);
		} catch (DuplicateElementException e) {
			throw new AlreadyExistingCircuitElementException("Circuit with name \"" + data.getName()
					+ "\" already exists.");
		}
		return theCircuit;
	}

	public Circuit modifyCircuit(CircuitDto data) throws InvalidCircuitElementException,
			CircuitElementNotFoundException {
		log.info("Modifying \"" + data.getName() + "\" circuit.");
		removeCircuit(data.getName());
		try {
			return makeCircuit(data);
		} catch (AlreadyExistingCircuitElementException e) {
			// Should never reach this since circuit has just been removed,
			// but just in case...
			throw new RuntimeException("Unreachable code reached...");
		}
	}

	public Circuit getCircuit(String name) throws CircuitElementNotFoundException {
		log.info("Retrieving \"" + name + "\" circuit.");
		return circuitRepository.getCircuitByName(name);
	}

	public void removeCircuit(String name) throws CircuitElementNotFoundException {
		log.info("Removing \"" + name + "\" circuit.");
		try {
			circuitRepository.remove(circuitRepository.getCircuitByName(name));
		} catch (ElementNotFoundException e) {
			throw new CircuitElementNotFoundException("Circuit with name \"" + name + "\" could not be found.");
		}
	}

}
